-- create OLTP write workload stored procedures for PostgreSQL

----------
----------

-- procedure oltp_write_01 (randbase)
-- increment randomly chosen updates.p_int by 1 and save old row in update_int_history
-- changes: updates.p_int, update_int_history
-- might use index on: updates.p_key
-- competes with: oltp_read_select_04, oltp_read_select_05, oltp_read_select_06, oltp_write_06
-- checks atomicity, asolation
-- single table 1 row select and update on an int, 1 row insert

drop function oltp_write_01 (int);
ERROR:  RemoveFunction: function 'oltp_write_01(int4)' does not exist
create function oltp_write_01 (int) returns int as '
declare
	randbase alias for $1;
	oldint	int;
begin
	set transaction isolation level serializable;

	select into oldint updates.p_int
		from updates
			where updates.p_key = randbase;
--			for update;
	if not found then
		raise exception ''Error in oltp_write_01: randbase = %'', randbase;
	end if;
	update updates set p_int = p_int + 1
		where updates.p_key = randbase;
	insert into update_int_history values (randbase, oldint, ''now'');

	return 0;
end;
' language 'plpgsql';

--

drop function oltp_write_01_check ();
ERROR:  RemoveFunction: function 'oltp_write_01_check()' does not exist
create function oltp_write_01_check () returns varchar as '
declare
	checkval1	float4;
	checkval2	float4;
begin
	select into checkval1 sum(updates.p_int) from updates;
	select into checkval1 checkval1 - count(*) from update_int_history;
	select into checkval2 int_sum from oltp_write_01_check_value;
--	select ''oltp_write_01_check should return two identical values. The actual values are '' || checkval1 || '' and '' || checkval2;

	if (checkval1 = checkval2) then
		return ''Consistency check passed.'';
	else
		return ''**CONSISTENCY CHECK FAILURE** in oltp_write_01.'';
	end if;

	return ''end oltp_write_01_check'';
end;
' language 'plpgsql';

--

drop function oltp_write_01_undo ();
ERROR:  RemoveFunction: function 'oltp_write_01_undo()' does not exist
create function oltp_write_01_undo () returns varchar as '
begin
        update updates
                set p_int = p_key
                where updates.p_int <> updates.p_key;
        delete from update_int_history;
        return ''Finished undoing effects of oltp_write_01'';
end;
' language 'plpgsql';

----------

-- procedure oltp_write_02 (randbase)
-- increment randomly chosen updates.p_signed by 1 and save old row in update_signed_history
-- changes: updates.p_signed, update_signed_history
-- might use index on: updates.p_key
-- competes with oltp_read_select_04, oltp_read_select_05, oltp_read_select_06, oltp_read_join_03
-- checks atomicity, isolation
-- single table 1 row select and update on an int, 1 row insert

drop function oltp_write_02 (int);
ERROR:  RemoveFunction: function 'oltp_write_02(int4)' does not exist
create function oltp_write_02 (int) returns int as '
declare
	randbase alias for $1;
        oldsigned      int;
begin
	set transaction isolation level serializable;

	select into oldsigned updates.p_signed
		from updates
			where updates.p_key = randbase;
--			for update;
	if not found then
		raise exception ''Error in oltp_write_02: randbase = %'', randbase;
	end if;
	update updates set p_signed = p_signed + 1
		where updates.p_key = randbase;
	insert into update_signed_history values (randbase, oldsigned, ''now'');

	return 0;
end;
' language 'plpgsql';

--

drop function oltp_write_02_check ();
ERROR:  RemoveFunction: function 'oltp_write_02_check()' does not exist
create function oltp_write_02_check () returns varchar as '
declare
	checkval1	float4;
	checkval2	float4;
begin
	select into checkval1 sum(updates.p_signed) from updates;
	select into checkval2 count(*) from update_signed_history;
--	select ''oltp_write_02_check should return two identical values (the number of times oltp_write_02 has been run). The actual values are '' || checkval1 || '' and '' || checkval2;

	if (checkval1 = checkval2) then
		return ''Consistency check passed.'';
	else
		return ''**CONSISTENCY CHECK FAILURE** in oltp_write_02.'';
	end if;

	return ''end oltp_write_02_check'';
end;
' language 'plpgsql';

--

drop function oltp_write_02_undo ();
ERROR:  RemoveFunction: function 'oltp_write_02_undo()' does not exist
create function oltp_write_02_undo () returns varchar as '
begin
	update updates
		set p_signed = update_signed_history.p_signed
		from update_signed_history, updates
		where update_signed_history.p_key = updates.p_key
		and update_signed_history.p_signed in
			(select min(update_signed_history.p_signed)
			from update_signed_history, updates
			where update_signed_history.p_key = updates.p_key
			group by update_signed_history.p_key);
        delete from update_signed_history;
        return ''Finished undoing effects of oltp_write_02'';
end;
' language 'plpgsql';

----------

-- procedure oltp_write_03 (randfivemill)
-- moves a randomly selected row from fivemill to del_history
-- changes: fivemill, del_history
-- might use index on: fivemill.h_key
-- competes with oltp_read_join_03
-- checks atomicity, isolation
-- single row select and insert, single row delete

drop function oltp_write_03 (int);
ERROR:  RemoveFunction: function 'oltp_write_03(int4)' does not exist
create function oltp_write_03 (int) returns int as '
declare
	randfivemill alias for $1;
begin
	set transaction isolation level serializable;

	insert into del_history
		select * from fivemill where fivemill.h_key = randfivemill;
	delete from fivemill
		where fivemill.h_key = randfivemill;

	return 0;
end;
' language 'plpgsql';

--

drop function oltp_write_03_check ();
ERROR:  RemoveFunction: function 'oltp_write_03_check()' does not exist
create function oltp_write_03_check () returns varchar as '
declare
	checkval1	int;
	checkval2	int;
begin
	select into checkval1 count(*) from fivemill;
	select into checkval2 count(*) from del_history;
--	select ''oltp_write_03_check should return exactly 5,000,000. The actual value is '' || checkval1 + checkval2;

	if (checkval1 + checkval2 = 50000) then
		return ''Consistency check passed.'';
	else
		return ''**CONSISTENCY CHECK FAILURE** in oltp_write_03.'';
	end if;

	return ''end oltp_write_03_check'';
end;
' language 'plpgsql';

--

drop function oltp_write_03_undo ();
ERROR:  RemoveFunction: function 'oltp_write_03_undo()' does not exist
create function oltp_write_03_undo () returns varchar as '
begin
	insert into fivemill select * from del_history;
	delete from del_history;
	return ''Finished undoing effects of oltp_write_03'';
end;
' language 'plpgsql';

----------

-- procedure oltp_write_04 (randfourmill)
-- modifies between 1 and 2 randomly chosen fourmill.t_name and fourmill.t_address values, increments the update counter oltp_write_04_count_updates.num_updates
-- changes: fourmill.t_name, fourmill.t_address, oltp_write_04_count_updates.num_updates
-- might use index on: fourmill.t_key
-- competes with nothing else
-- checks atomicity
-- single table in range select and update on 2 character fields, 1 int field

drop function oltp_write_04 (int);
ERROR:  RemoveFunction: function 'oltp_write_04(int4)' does not exist
create function oltp_write_04 (int) returns int as '
declare
	randfourmill alias for $1;
	numupdates	int;
begin
	set transaction isolation level serializable;

	select into numupdates count(*) from fourmill
		where (t_key between randfourmill and randfourmill + 500)
		and (t_name <> ''NewName'');
	if not found then
		raise exception ''Error in oltp_write_04: randfourmill = %'', randfourmill;
	end if;
	update fourmill
		set t_name = ''NewName'', t_address = ''New Address 320B Lakeside Dr., Foster City, CA''
		where (t_key between randfourmill and randfourmill + 500)
		and (t_name <> ''NewName'');
	update oltp_write_04_count_updates
		set num_updates = num_updates + numupdates;

	return 0;
end;
' language 'plpgsql';

--

drop function oltp_write_04_check ();
ERROR:  RemoveFunction: function 'oltp_write_04_check()' does not exist
create function oltp_write_04_check () returns varchar as '
declare
	checkval1	int;
	checkval2	int;
begin
	select into checkval1 count(*) from fourmill
		where fourmill.t_name = ''NewName'';
	select into checkval2 oltp_write_04_count_updates.num_updates from oltp_write_04_count_updates;
--	select ''oltp_write_04_check should return two identical values. The actual values are '' || checkval1 || '' and '' || checkval2;

	if (checkval1 = checkval2) then
		return ''Consistency check passed.'';
	else
		return ''**CONSISTENCY CHECK FAILURE** in oltp_write_04.'';
	end if;

	return ''end oltp_write_04_check'';
end;
' language 'plpgsql';

--

drop function oltp_write_04_undo ();
ERROR:  RemoveFunction: function 'oltp_write_04_undo()' does not exist
create function oltp_write_04_undo () returns varchar as '
begin
	update fourmill
		set t_name = ''OldName''
		where fourmill.t_name = ''NewName'' and fourmill.t_address = ''New Address 320B Lakeside Dr., Foster City, CA'';
	update oltp_write_04_count_updates
		set num_updates = 0;
	return ''Finished undoing effects of oltp_write_04'';
end;
' language 'plpgsql';

----------

-- procedure oltp_write_05 (randbase)
-- does an update on 10 contiguous rows of updates.p_decim and then rolls the changes back
-- changes: (nothing)
-- might use index on updates.p_key
-- competes with oltp_write_06, dss_select_05, dss_select_06, dss_select_07, dss_select_08, dss_select_09
-- checks atomicity, consistency, isolation
-- single table range update and rollback

drop function oltp_write_05 (int);
ERROR:  RemoveFunction: function 'oltp_write_05(int4)' does not exist
create function oltp_write_05 (int) returns int as '
declare
	randbase alias for $1;
begin
	set transaction isolation level serializable;

	update updates
		set p_decim = abs(p_decim) - 2000000001
		where p_key between randbase and randbase + 9;
--	rollback;
	raise exception ''doing rollback'';

	return 0;
end;
' language 'plpgsql';

--

drop function oltp_write_05_check ();
ERROR:  RemoveFunction: function 'oltp_write_05_check()' does not exist
create function oltp_write_05_check () returns varchar as '
declare
	checkval1	int;
begin
	select into checkval1 count(*) from updates
		where updates.p_decim < -1000000000;
--	select ''oltp_write_05_check should return exactly 0. The actual value is '' || checkval1;

	if (checkval1 = 0) then
		return ''Consistency check passed.'';
	else
		return ''**CONSISTENCY CHECK FAILURE** in oltp_write_05.'';
	end if;

	return ''end oltp_write_05_check'';
end;
' language 'plpgsql';

--

drop function oltp_write_05_undo ();
ERROR:  RemoveFunction: function 'oltp_write_05_undo()' does not exist
create function oltp_write_05_undo () returns varchar as '
begin
-- procedure is self-undoing
	return ''Finished undoing effects of oltp_write_05'';
end;
' language 'plpgsql';

CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
CREATE
EOF
